import Foundation
import ImCommon

// 客户端
class Client: NSObject {
    private let mServer: Server     // 服务器
    private let mSocket: Int32      // 套接字
    private var mThread: Thread!    // 线程

    /**
     * 构造方法。
     * @param server    服务器
     * @param sock      套接字
     */
    public init(_ server: Server, sock: Int32) {
        // 初始化成员
        mServer = server
        mSocket = sock
        super.init()
        
        // 开启接收数据的线程
        mThread = Thread(target: self, selector: #selector(client_thread), object: nil)
        mThread.start()
    }
    
    /**
     * 客户端线程。
     */
    @objc private func client_thread() {
        var result: Int
        var sizeBuffer: [UInt8]
        var proBuffer: [UInt8]
        
        while true {
            // 接收数据长度
            sizeBuffer = [UInt8](repeating: 0, count: MemoryLayout<Int>.size)
            result = recv(mSocket, &sizeBuffer, MemoryLayout<Int>.size, 0)
            if result <= 0 {
                break
            }
            var dataSize = 0
            memcpy(&dataSize, &sizeBuffer, MemoryLayout<Int>.size)
            
            // 接收数据
            proBuffer = [UInt8](repeating: 0, count: dataSize)
            result = recv(mSocket, &proBuffer, dataSize, 0)
            if result <= 0 {
                break
            }
            
            // 将数据转换成协议
            let pro = ImProtocol.unArchive(proBuffer, count: dataSize)

            // 处理协议
            mServer.onGetMessageFromClient(self, pro: pro)
        }
    }
    
    /**
     * 关闭。
     */
    public func close() {
        Darwin.close(mSocket)
    }

    /**
    * 发送数据。
    * @param pro    协议
    */           
    public func sendData(_ pro: ImProtocol) {
        // 将协议转换成数据
        let data = ImProtocol.archive(pro)

        // 发送数据长度
        var dataSize = data.count
        send(mSocket, &dataSize, MemoryLayout<Int>.size, 0)
        
        // 发送数据
        send(mSocket, data, dataSize, 0)
        
        // 防止发送过快导致客户端无法响应
        Thread.sleep(forTimeInterval: 0.01)
    }
}
